/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package acceso.servicio.correo;

import wf.dto.correo.Tbcorreo;
import wf.dto.correo.Tbdestin;
import acceso.hibernate.AQuery;
import acceso.hibernate.AccesoHibernate;
import acceso.servicio.Servicio;
import acceso.util.Escritor;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.StatelessSession;

/**
 *
 * @author romulogalindo
 */
public class SCorreo extends Servicio implements Icorreo {

    static Session session;
    HashMap pendientes = new HashMap();

    public SCorreo(Properties config) {
        super(config);
    }

    @Override
    public boolean iniciar() {
        //
        try {
            Properties props_correo = new Properties();
            System.out.println("size:" + config.size());
            Enumeration props = config.propertyNames();
            while (props.hasMoreElements()) {
                String keys = props.nextElement().toString();
                System.out.println("keys:" + keys);
                props_correo.setProperty(keys, config.getProperty(keys));
            }
            System.out.println("======================");
            session = Session.getInstance(props_correo, null);
            System.out.println("Conexión hacia el servidor de correo [OK]");
            System.out.println("======================");

            //MimeMessage msg = new MimeMessage(session);

            System.out.println("Iniciando servicio de correo!");
            return true;
        } catch (Exception ep) {
            return false;
        }
    }

    @Override
    public boolean detener() {
        System.out.println("Fin del servicio de correo");
        return false;
    }

    public int envia_correo(int id_correo) throws Exception {
        /*
         MimeMessage mensaje = new MimeMessage(session);

         put_list(mensaje, id_correo, true);
         */

        int result = 0;
        Tbcorreo correo = get_correo_por_id(id_correo);
        char e = 'P';
        if (correo.getTiEstado() == 'E') {
            throw new Exception("El correo ya fue enviado");
        }

        MimeMessage mensaje = genera_mensaje(correo, get_destinatarios_por_id(id_correo));

        //System.out.println("mensaje:" + mensaje);

        try {
            Transport.send(mensaje);
            e = 'E';
            result = 1;
        } catch (Exception ep) {
            result = 0;
            //System.out.println("Error envio:"+ep.getMessage());

            if (ep instanceof javax.mail.SendFailedException) {
                e = 'P';
                //System.out.println(">>"+ep.getClass()+"::"+e);

            } else {
                e = 'F';
                //System.out.println(">>"+ep.getClass()+"::"+e);

            }



            //throw new Exception("Mensaje no enviado." );
        }

        try {
            actualizar_estado_correo(id_correo, e);

        } catch (Exception ep) {
            Escritor.escribe_errors("Error update:" + ep.getMessage());
        }

        if (e == 'P') {
            throw new Exception("El servidor de correo esta inoperativo. Por favor intentelo mas tarde.");
        }
        if (e == 'F') {
            throw new Exception("Mensaje no enviado.");
        }
        System.out.println("result:" + result);

        return result;
    }

    public String envia_correo_job() throws Exception {

        List c = get_correo_por_estado("P");
        for (int i = 0; i < c.size(); i++) {
            Tbcorreo correo = (Tbcorreo) c.get(i);
            //put_list( correo.getIdCorreo(), genera_mensaje( correo, get_destinatarios_por_id(correo.getIdCorreo()) ) );
            put_list(genera_mensaje(correo, get_destinatarios_por_id(correo.getIdCorreo())), correo.getIdCorreo(), false);
        }

        MimeMessage mensaje = new MimeMessage(session);

        //put_list(mensaje, id_correo);

        /*
         MimeMessage mensaje = genera_mensaje(get_correo_por_id(id_correo), get_destinatarios_por_id(id_correo));
         System.out.println("mensaje:"+mensaje);
         Transport.send(mensaje);
         */

        return "JOB! enviado a la cola";
    }

    public synchronized void put_list(MimeMessage mensaje, long id_correo, boolean x) {
        if (pendientes.containsKey(id_correo)) {
            if (x) {
                //buscarlo!
            }
        } else {
            pendientes.put(id_correo, mensaje);

        }

    }

    //METODOS PROPIOS
    public void actualizar_estado_correo(long id_correo, char il_estado) throws Exception {
        StatelessSession HSESSION = null;
        try {
            HSESSION = AccesoHibernate.getSessionFactory().openStatelessSession();//SESSION ABIERTA
            HSESSION.beginTransaction();

            SQLQuery sqlQuery = HSESSION.createSQLQuery("update correo.tbcorreo set ti_estado = '" + il_estado + "' where id_correo = " + id_correo);
            int r = sqlQuery.executeUpdate();
            HSESSION.getTransaction().commit();
        } finally {
            HSESSION.close();
        }
    }

    public Tbcorreo get_correo_por_id(long id_correo) throws HibernateException {
        Tbcorreo correo = null;

        StatelessSession HSESSION = null;
        AQuery HQUERY = null;
        try {
            HSESSION = AccesoHibernate.getSessionFactory().openStatelessSession();//SESSION ABIERTA
            HQUERY = new AQuery(HSESSION.createQuery("from Tbcorreo where idCorreo = " + id_correo));
            System.out.println(HQUERY.getQuery());
            Object obj = HQUERY.getMquery().uniqueResult();
            correo = (Tbcorreo) obj;
        } finally {
            HSESSION.close();
        }
        return correo;
    }

    public List get_correo_por_estado(String estado) throws HibernateException {
        List l_correo = null;

        StatelessSession HSESSION = null;
        AQuery HQUERY = null;
        try {
            HSESSION = AccesoHibernate.getSessionFactory().openStatelessSession();//SESSION ABIERTA
            HQUERY = new AQuery(HSESSION.createQuery("from Tbcorreo where tiEstado = " + estado));
            //System.out.println(HQUERY.getQuery());
            l_correo = HQUERY.getMquery().list();
            //correo = (Tbcorreo) obj;
        } finally {
            HSESSION.close();
        }
        return l_correo;
    }

    public List get_destinatarios_por_id(long id_correo) throws HibernateException {
        List destin = null;

        StatelessSession HSESSION = null;
        AQuery HQUERY = null;
        try {
            HSESSION = AccesoHibernate.getSessionFactory().openStatelessSession();//SESSION ABIERTA
            HQUERY = new AQuery(HSESSION.createQuery("from Tbdestin where idCorreo = " + id_correo));
            //System.out.println(HQUERY.getQuery());
            destin = HQUERY.getMquery().list();
        } finally {
            HSESSION.close();
        }
        return destin;
    }

    public InternetAddress valida_correo(String email, String name) throws UnsupportedEncodingException, AddressException {
        InternetAddress address = null;
        name = name + "";
        //if(name.contentEquals("")) address = InternetAddress.parse(email, false)[0];
        if (name.contentEquals("")) {
            address = new InternetAddress(email);
        } else {
            address = new InternetAddress(email, name, "ISO-8859-1");
        }
        return address;
    }

    public InternetAddress[] get_all_to(List<Tbdestin> destin) throws Exception {
        InternetAddress[] email_to = null;
        List COPIAR_A = new ArrayList();

        for (int i = 0; i < destin.size(); i++) {
            if (destin.get(i).getTiDestin().contentEquals("P")) {
                COPIAR_A.add(new InternetAddress(destin.get(i).getEmDestin()));
            }
        }

        if (COPIAR_A.size() > 0) {
            email_to = new InternetAddress[COPIAR_A.size()];
            for (int i = 0; i < COPIAR_A.size(); i++) {
                email_to[i] = (InternetAddress) COPIAR_A.get(i);
            }
        }

        return email_to;
    }

    public InternetAddress[] get_all_cc(List<Tbdestin> destin) throws Exception {
        InternetAddress[] email_to = null;
        List CON_COPIA = new ArrayList();

        for (int i = 0; i < destin.size(); i++) {
            if (destin.get(i).getTiDestin().contentEquals("C")) {
                CON_COPIA.add(new InternetAddress(destin.get(i).getEmDestin()));
            }
        }

        if (CON_COPIA.size() > 0) {
            email_to = new InternetAddress[CON_COPIA.size()];
            for (int i = 0; i < CON_COPIA.size(); i++) {
                email_to[i] = (InternetAddress) CON_COPIA.get(i);
            }
        }

        return email_to;
    }

    public InternetAddress[] get_all_cco(List<Tbdestin> destin) throws Exception {
        InternetAddress[] email_to = null;
        List C_COPIA_O = new ArrayList();
        for (int i = 0; i < destin.size(); i++) {
            if (destin.get(i).getTiDestin().contentEquals("O")) {
                C_COPIA_O.add(new InternetAddress(destin.get(i).getEmDestin()));
            }
        }

        if (C_COPIA_O.size() > 0) {
            email_to = new InternetAddress[C_COPIA_O.size()];
            for (int i = 0; i < C_COPIA_O.size(); i++) {
                email_to[i] = (InternetAddress) C_COPIA_O.get(i);
            }
        }

        return email_to;
    }

    public String get_file(String codigo, String nombre, boolean comprimir) {
        FileInputStream fis = null;
        File fout = null;
        boolean existe = true;
        String nombre_codigo = "";
        String nombre_codigo_extension = "";
        String nombre_codigo_sinext = "";
        String NAME = "";
        try {
            fis = new FileInputStream("/backup/" + codigo);
            nombre_codigo = codigo.substring(codigo.lastIndexOf('/'));
            nombre_codigo_extension = nombre_codigo.substring(nombre_codigo.lastIndexOf("."));
            nombre_codigo_sinext = nombre_codigo.replaceAll("." + nombre_codigo_sinext, "");

            fout = new File("/tmp/" + nombre_codigo);

            FileOutputStream fos = new FileOutputStream(fout, false);

            byte[] buffer = new byte[8192];
            int bytesLeidos = 0;
            while ((bytesLeidos = fis.read(buffer, 0, 8192)) != -1) {
                fos.write(buffer, 0, bytesLeidos);
            }
            fos.close();
            NAME = "/tmp/" + nombre_codigo;
            if (comprimir) {
                File fa = new File("/tmp/" + nombre_codigo_sinext + ".zip");
                fa.delete();

                //crear buffer para leer el archivo
                byte[] buf = new byte[1024 * 1024 * 10];//10MB

                try {

                    //1.Crear el zip
                    ZipOutputStream out = new ZipOutputStream(new FileOutputStream("/tmp/" + nombre_codigo_sinext + ".zip"));
                    //2.Comprimir archivo deseado
                    FileInputStream in = new FileInputStream("/tmp/" + nombre_codigo);
                    //3.agregar zip entry a output stream
                    out.putNextEntry(new ZipEntry(nombre));
                    //Transfiero bytes del archivo al zip
                    int len = 0;
                    while ((len = in.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }

                    //completo la entrada al zip
                    out.closeEntry();
                    in.close();

                    //completo el zip
                    out.close();

                } catch (IOException e) {
                    System.out.println("e" + e.getMessage());
                }
                NAME = "/tmp/" + nombre_codigo_sinext + ".zip";
            }


        } catch (Exception ex) {
            existe = false;
            ex.printStackTrace();
        }
        return NAME;
    }

    public MimeMessage genera_mensaje(Tbcorreo correo, List destinatarios) throws Exception {

        MimeMessage mail = null;

        if (correo == null) {
            throw new Exception("No hay datos de correo para ese id_correo[" + correo.getIdCorreo() + "]");
        } else {
            if (destinatarios == null | destinatarios.size() == 0) {
                throw new Exception("No se especificaron destinatarios para el id_correo[" + correo.getIdCorreo() + "]");
            } else {
                mail = new MimeMessage(session);

                //Creo EMAIL
                mail.addHeader("Content-Type", "text/plain; charset=\"ISO-8859-1\"");
                //mail.addHeader("Content-Type", "text/plain; charset=\"UTF-8\"");
                Escritor.escribe_frawor("Creación de mail en blanco. [OK]");

                //BASE PARA DATOS ADJUNTOS
                MimeMultipart mime_multipart = new MimeMultipart();

                //BASE PARA CONTENIDO TXT / HTML
                MimeBodyPart body_multipart = new MimeBodyPart();

                //CONSEGUIR EL REMITENTE
                InternetAddress remitente = null;
                //remitente = valida_correo(correo.getEmRemite(), new String(correo.getNoRemite().getBytes("ISO-8859-1"), "UTF-8"));
                remitente = valida_correo(correo.getEmRemite(), correo.getNoRemite());
                mail.setFrom(remitente);
                Escritor.escribe_transa("FROM:" + remitente.getAddress());
                Escritor.escribe_frawor("Agregando remitente. [OK]");

                //CONSEGUIR LISTA DE DESTINARIOS DIRECTOS
                InternetAddress[] correo_destinatario = null;
                correo_destinatario = get_all_to(destinatarios);
                if (correo_destinatario != null) {
                    mail.setRecipients(Message.RecipientType.TO, correo_destinatario);
                    for (int i = 0; i < correo_destinatario.length; i++) {
                        Escritor.escribe_transa("TO:" + correo_destinatario[0].getAddress());
                    }
                } else {
                    throw new Exception("No se especifico destinatario o no es valido.");
                }
                Escritor.escribe_frawor("Agregando destinatario directo. [OK]");


                //CONSEGUIR LISTA DE DESTINARIOS CON COPIA
                InternetAddress[] destinatarios_cc = null;
                destinatarios_cc = get_all_cc(destinatarios);
                if (destinatarios_cc != null) {
                    mail.setRecipients(Message.RecipientType.CC, destinatarios_cc);
                    for (int i = 0; i < destinatarios_cc.length; i++) {
                        Escritor.escribe_transa("CC:" + destinatarios_cc[i].getAddress());
                    }
                }
                Escritor.escribe_frawor("Agregando destinatario con copia. [OK]");

                //CONSEGUIR LISTA DE DESTINARIOS CON COPIA OCULTA
                InternetAddress[] destinatarios_cco = null;
                destinatarios_cco = get_all_cco(destinatarios);
                if (destinatarios_cco != null) {
                    mail.setRecipients(Message.RecipientType.BCC, destinatarios_cco);
                    for (int i = 0; i < destinatarios_cco.length; i++) {
                        Escritor.escribe_transa("CCO:" + destinatarios_cco[i].getAddress());
                    }
                }
                Escritor.escribe_frawor("Agregando destinatario con copia oculta. [OK]");

                //AGREGAR RESPONDER A!
                InternetAddress[] responder_a = new InternetAddress[1];
                responder_a[0] = valida_correo(correo.getEmRemite(), correo.getNoRemite());
                if (responder_a[0] != null) {
                    mail.setReplyTo(responder_a);
                    Escritor.escribe_transa("REPLY:" + responder_a[0].getAddress());
                }
                Escritor.escribe_frawor("Agregando responder a. ...[OK]");

                //ASUNTO DEL MAIL

                //mail.setSubject(new String(correo.getNoAsunto().getBytes("ISO-8859-1"), "UTF-8"));
                mail.setSubject(correo.getNoAsunto());
                Escritor.escribe_transa("SUBJECT:" + correo.getNoAsunto());
                Escritor.escribe_frawor("Agregando asunto. [OK]");

                //FECHA/HORA DEL MAIL
                Date d = new Date();
                mail.setSentDate(d);
                Escritor.escribe_transa("SUBJECT:" + d);
                Escritor.escribe_frawor("Agregando fecha. [OK]");

                //CUERPO DEL MENSAJE
                if ((correo.getIlAdjunt() + "").contentEquals("S")) {
                    MimeBodyPart body_multipart_file = new MimeBodyPart();
                    DataHandler data_handler = null;
                    boolean comprimir = (correo.getIlCompre() + "").contentEquals("S") ? true : false;

                    FileDataSource file_data = null;
                    file_data = new FileDataSource(get_file(correo.getCoAdjunt(), correo.getNoAdjunt(), comprimir));
                    data_handler = new DataHandler(file_data);

                    body_multipart_file.setDataHandler(data_handler);
                    body_multipart_file.setFileName(correo.getNoAdjunt() + "" + (comprimir ? ".zip" : ""));

                    mime_multipart.addBodyPart(body_multipart_file);
                }

                //CONTENIDO DEL BODY
                if ((correo.getTiConten() + "").contentEquals("") | (correo.getTiConten() + "").contentEquals("TH")) {
                    //body_multipart.setContent(new String(correo.getNoMensaj().getBytes("ISO-8859-1"), "UTF-8"), "text/html; charset=ISO-8859-1");
                    //body_multipart.setContent(new String(correo.getNoMensaj().getBytes("ISO-8859-1"), "UTF-8"), "text/html; charset=UTF-8");
                    //body_multipart.setContent(correo.getNoMensaj(), "text/html; charset=ISO-8859-1");

                    body_multipart.setHeader("Content-Type", "text/html; charset=\"ISO-8859-1\"");
                    body_multipart.setContent(correo.getNoMensaj(), "text/html;  charset=\"ISO-8859-1\"");

                    body_multipart.setHeader("Content-Transfer-Encoding", "quoted-printable");

                    //body_multipart.setContent(correo.getNoMensaj(), "text/html;");
                    Escritor.escribe_transa("BODY:" + correo.getNoMensaj());
                    Escritor.escribe_frawor("Cuerpo del mensaje HTML. [OK]");
                } else {
                    //body_multipart.setContent(new String(correo.getNoMensaj().getBytes("ISO-8859-1"), "UTF-8"), "text/plain; charset=ISO-8859-1");
                    //body_multipart.setContent(new String(correo.getNoMensaj().getBytes("ISO-8859-1"), "UTF-8"), "text/plain; charset=UTF-8");
                    body_multipart.setHeader("Content-Type", "text/plain; charset=\"ISO-8859-1\"");
                    body_multipart.setContent(correo.getNoMensaj(), "text/plain;  charset=\"ISO-8859-1\"");
                    body_multipart.setHeader("Content-Transfer-Encoding", "quoted-printable");
                    //body_multipart.setContent(correo.getNoMensaj(), "text/plain;");
                    Escritor.escribe_transa("BODY:" + correo.getNoMensaj());
                    Escritor.escribe_frawor("Cuerpo del mensaje plain/text. [OK]");
                }
                mime_multipart.addBodyPart(body_multipart);
                Escritor.escribe_frawor("Mensaje listo. [OK]");

                //CONTENIDO AL MAIL
                mail.setContent(mime_multipart);
                Escritor.escribe_frawor("Listo para enviar. [OK]");

                //ENVIO DE CORREO
                //Transport.send(mail);
                //response = "OK";
                //Escritor.escribe_frawor("Mensaje enviado. [OK]");
            }
        }

        return mail;
    }
}
